// $Id: ptr.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPCOM_IMPL_PTR_HPP
#define XPCOM_IMPL_PTR_HPP

#include <xpcom/config.hpp>
#include <xpcom/ptr.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

namespace xpcom {
namespace impl {

//
// XPCOM implementation argument translators.
// Note: The out/inout arguments must not be null.
//
// ptr_in(T*) --> noref_ptr<T>
// ptr_in_void(void*) --> noref_ptr<interface>
// ptr_out(T**) --> ref_ptr<T>&
// ptr_out_void(void**) --> ref_ptr<interface>&
// ptr_inout(T**) --> ref_ptr<T>&
// ptr_inout_void(void**) --> ref_ptr<interface>&
//

template <typename T>
XPCOM_FORCEINLINE
noref_ptr<T> ptr_in(T* p)
{
    return p;
}

XPCOM_FORCEINLINE
noref_ptr<interface> ptr_in_void(void* p)
{
    return static_cast<interface*>(p);
}

template <typename T>
XPCOM_FORCEINLINE
ref_ptr<T>& ptr_out(T** p)
{
    *p = 0; // XXX to avoid bad release, caller SHOULD pass null pointer
    return *reinterpret_cast<ref_ptr<T>* >(p);
}

XPCOM_FORCEINLINE
ref_ptr<interface>& ptr_out_void(void** p)
{
    *p = 0;
    return *reinterpret_cast<ref_ptr<interface>* >(p);
}

template <typename T>
XPCOM_FORCEINLINE
ref_ptr<T>& ptr_inout(T** p)
{
    return *reinterpret_cast<ref_ptr<T>* >(p);
}

XPCOM_FORCEINLINE
ref_ptr<interface>& ptr_inout_void(void** p)
{
    return *reinterpret_cast<ref_ptr<interface>* >(p);
}

} // namespace xpcom::impl
} // namespace xpcom

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // XPCOM_IMPL_PTR_HPP
